/* ************************************************************************

   qooxdoo - the new era of web development

   http://qooxdoo.org

   Copyright:
     2006-2007 STZ-IDA, Germany, http://www.stz-ida.de

   License:
     LGPL: http://www.gnu.org/licenses/lgpl.html
     EPL: http://www.eclipse.org/org/documents/epl-v10.php
     See the LICENSE file in the project's top-level directory for details.

   Authors:
     * Andreas Junghans (lucidcake)

************************************************************************ */

package net.sf.qooxdoo.rpc;

import java.util.ArrayList;


/**
 * Utilities for string handling.
 */

public class StringUtils {

    private static final int STATE_DEFAULT = 1;
    private static final int STATE_BACKSLASH = 2;

    
    /**
     * Escapes a specified character in a string (and also escapes
     * backslashes since a backslash is used as the escape character).
     *
     * @param       source              the string to process.
     * @param       toEscape            the char to escape.
     *
     * @return      the new string (or <code>null</code> if
     *              <code>source</code> is <code>null</code>).
     */
    
    public static String escapeChar(String source, char toEscape) {
        if (source == null) {
            return null;
        }
        int length = source.length();
        StringBuffer result = new StringBuffer(length + 10);
            // length + 10 is just a guess, but better than simply
            // starting from scratch
        char c;
        for (int i = 0; i < length; ++i) {
            c = source.charAt(i);
            if (c == toEscape || c == '\\') {
                result.append('\\');
            }
            result.append(c);
        }
        return result.toString();
    }
    

    /**
     * Tokenizes a string and takes into account escaping. The source string
     * may contain the seperator character escaped with a backslash. The
     * backslash itself can be generated by using a double backslash.
     * <p>
     * More than one separator in a row leeds to empty strings in the
     * resulting array ("a;;b" results in "a", "", "b"). The last trailing
     * separator is ignored ("a;;b;" results in "a", "", "b" - same as
     * above -, while "a;;b;;" results in "a", "", "b", "").
     * </p>
     *
     * @param       source              the string to tokenize.
     * @param       separator           the separator character.
     *
     * @return      the tokenized string (or <code>null</code> if
     *              <code>source</code> is <code>null</code>).
     */
    
    public static String[] tokenize(String source, char separator) {
        if (source == null) {
            return null;
        }
        int length = source.length();
        ArrayList result = new ArrayList();
        StringBuffer currentString = new StringBuffer();
        char c;
        int state = STATE_DEFAULT;
        for (int i = 0; i < length; ++i) {
            c = source.charAt(i);
            switch (state) {
                case STATE_DEFAULT:
                    if (c == '\\') {
                        state = STATE_BACKSLASH;
                    } else if (c == separator) {
                        result.add(currentString.toString());
                        currentString = new StringBuffer();
                    } else {
                        currentString.append(c);
                    }
                    break;
                case STATE_BACKSLASH:
                    currentString.append(c);
                    state = STATE_DEFAULT;
                    break;
            }
        }
        if (state == STATE_BACKSLASH) {
            throw new IllegalArgumentException("The string to tokenize ends with a single backslash");
        }
        if (currentString.length() > 0) {
            result.add(currentString.toString());
        }
        return (String[])result.toArray(new String[result.size()]);
    }
    
}

